package org.example;

import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.util.Objects;

public class SecretKeyUtil {
    private static final String RSA_ALGORITHM = "RSA";
    private static final String DES_ALGORITHM = "DES";

    public static KeyPair createRSAKey() {
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA_ALGORITHM);
            keyPairGenerator.initialize(512);
            return keyPairGenerator.generateKeyPair();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new RuntimeException("请检查使用的算法配置", e);
        }
    }

    public static SecretKey createDESKey() {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(DES_ALGORITHM);
            keyGenerator.init(56);
            return keyGenerator.generateKey();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new RuntimeException("请检查使用的算法配置", e);
        }
    }

    public static Key generateDESKey(byte[] key) {
        try {
            DESKeySpec desKeySpec = new DESKeySpec(key);
            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
            return secretKeyFactory.generateSecret(desKeySpec);
        } catch (InvalidKeyException | NoSuchAlgorithmException | InvalidKeySpecException e) {
            e.printStackTrace();
            throw new RuntimeException("算法配置有误", e);
        }
    }

    public static byte[] encryptRSA(Key key, byte[] data) {
        return encrypt(RSA_ALGORITHM, key, data);
    }

    public static byte[] decryptRSA(Key key, byte[] data) {
        return decrypt(RSA_ALGORITHM, key, data);
    }

    public static byte[] encryptDES(Key key, byte[] data) {
        return encrypt(DES_ALGORITHM, key, data);
    }

    public static byte[] decryptDES(Key key, byte[] data) {
        return decrypt(DES_ALGORITHM, key, data);
    }

    private static byte[] encrypt(String algorithm, Key key, byte[] data) {
        try {
            Cipher cipher = getRSACipher(algorithm);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            return cipher.doFinal(data);
        } catch (IllegalBlockSizeException | BadPaddingException | InvalidKeyException e) {
            e.printStackTrace();
            throw new RuntimeException("请检查使用的算法配置", e);
        }
    }

    private static byte[] decrypt(String algorithm, Key key, byte[] data) {
        try {
            Cipher cipher = getRSACipher(algorithm);
            cipher.init(Cipher.DECRYPT_MODE, key);
            return cipher.doFinal(data);
        } catch (IllegalBlockSizeException | BadPaddingException | InvalidKeyException e) {
            e.printStackTrace();
            throw new RuntimeException("请检查使用的算法配置", e);
        }
    }

    private static Cipher getRSACipher(String algorithm) {
        try {
            return Cipher.getInstance(algorithm);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            e.printStackTrace();
            throw new RuntimeException("请检查使用的算法配置", e);
        }
    }

    public static void main(String[] args) {
        // 测试rsa加解密
        KeyPair rsaKey = createRSAKey();
        String msg = "one";
        byte[] bytes = encryptRSA(rsaKey.getPrivate(), msg.getBytes(StandardCharsets.UTF_8));
        String result = new String(decryptRSA(rsaKey.getPublic(), bytes), StandardCharsets.UTF_8);
        if (!Objects.equals(msg, result)) {
            throw new RuntimeException(String.format("rsa加解密测试用利失败，msg=%s, result=%s", msg, result));
        }

        // 测试des加解密
        SecretKey secretKey = createDESKey();
        byte[] bytes1 = encryptDES(secretKey, msg.getBytes(StandardCharsets.UTF_8));
        String result1 = new String(decryptDES(secretKey, bytes1), StandardCharsets.UTF_8);
        if (!Objects.equals(msg, result)) {
            throw new RuntimeException(String.format("rsa加解密测试用利失败，msg=%s, result=%s", msg, result1));
        }
    }
}
